import java.util.Scanner;

public class Test {
    /**
     * 认识线程
     *      6.volatile关键字
     *      7.wait和notify
     */

    /**
     * wait和notify
     *      wait方法
     *      notify方法
     *      wait和sleep对比
     */
    public static void main(String[] args) {
        /**
         * wait和sleep对比
         *      1.wait()需要搭配synchronized,sleep()不需要
         *      2.wait()是Object方法,sleep是Thread方法
         */
    }
    public static void main5(String[] args) throws InterruptedException {
        /**
         * notify方法
         *      1.通知wait线程唤醒wait线程
         *      2.如果有多个wait线程,随机唤醒
         *      3.当notify线程执行后,不会马上释放锁,要notify线程执行完毕后,才能释放锁
         *
         * notifyAll方法
         *      1.唤醒所有wait等待线程
         */
        Object locker = new Object();
        Object locker2 = new Object();
        Thread t1 = new Thread(()-> {
            synchronized (locker) {
                System.out.println("t1等待之前: ");
                try {
                    locker.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("t1等待之后: ");
            }
        });
        Thread t2 = new Thread(()-> {
            synchronized (locker) {
                System.out.println("t2等待之前: ");
                try {
                    locker.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("t2等待之后: ");
            }
        });

        Thread t3 = new Thread(()-> {
            synchronized (locker) {
                System.out.println("t3通知之前: ");
                locker.notifyAll();
                System.out.println("t3通知之后: ");
            }
        });

        t1.start();
        t2.start();
        Thread.sleep(100);
        t3.start();
    }
    public static void main4(String[] args) {
        /**
         * wait方法 -> 可以设定防死等
         *      调用后:
         *          1.使当前代码进入等待状态
         *          2.释放当前锁
         *          3.满足一定条件时被唤醒,重新尝试获取这个锁
         *      结束条件:
         *          1.其它线程调用notify方法
         *          2.wait等待超时
         *          3.其它线程调用interrupted方法,导致wait抛出异常
         *
         */
        Object locker = new Object();
        Thread t1 = new Thread(()-> {
            synchronized (locker) {
                System.out.println("等待之前: ");
                try {
                    locker.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("等待之后");
            }
        });

        t1.start();
    }
    /**
     * volatile关键字->修饰变量
     *      1.volatile保证内存可见性
     *      2.volatile不能保证原子性
     */
    public static void main3(String[] args) {
        /**
         * volatile不能保证原子性
         *      多线程情况下,不能保证操作是以原子性完成
         */
    }
    public static volatile int count = 0;//变量添加volatile保存内存可见性问题
    public static void main2(String[] args) {
        Thread t1 = new Thread(() -> {
            while(count == 0) {

            }
            System.out.println("循环结束");
        });

        Scanner scanner = new Scanner(System.in);
        Thread t2 = new Thread(() -> {
            count = scanner.nextInt();
        });

        t1.start();
        t2.start();
    }
    public static void main1(String[] args) {
        //内存可见性引起的线程不安全问题->本质内存可见性引起的问题,t2线程进行load操作优化,t1没有感知到
        Thread t1 = new Thread(() -> {
            while(count == 0) {

            }
            System.out.println("循环结束");
        });

        Scanner scanner = new Scanner(System.in);
        Thread t2 = new Thread(() -> {
            int a = scanner.nextInt();
            System.out.println(a);
        });

        t1.start();
        t2.start();
    }
}
